package cn.cangfei.massage.service.impl;

import cn.cangfei.massage.dto.param.MassageProductParam;
import cn.cangfei.massage.dto.update.MassageProductDto;
import cn.cangfei.massage.dto.update.MassageProductFinalDto;
import cn.cangfei.massage.entity.MassageProduct;
import cn.cangfei.massage.entity.MassageProductCategory;
import cn.cangfei.massage.entity.UserBasicInfo;
import cn.cangfei.massage.entity.VisitProduct;
import cn.cangfei.massage.exception.YyghException;
import cn.cangfei.massage.mapper.MassageProductMapper;
import cn.cangfei.massage.service.IMassageProductService;
import cn.cangfei.massage.service.IMassageProductCategoryService;
import cn.cangfei.massage.service.IUserBasicInfoService;
import cn.cangfei.massage.service.IVisitProductService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;


@Service
public class MassageProductServiceImpl extends ServiceImpl<MassageProductMapper, MassageProduct> implements IMassageProductService {

    @Resource
    private MassageProductMapper massageProductMapper;

    @Resource
    private IUserBasicInfoService userBasicInfoService;

    @Resource
    private IVisitProductService visitProductService;

    @Resource
    private IMassageProductCategoryService massageProductCategoryService;

    /**
     * 判断是否存在名称
     *
     * @param name
     * @return
     */
    @Override
    public boolean count(String name) {
        LambdaQueryWrapper<MassageProduct> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(MassageProduct::getName, name);
        MassageProduct one = massageProductMapper.selectOne(wrapper);
        return one != null;
    }

    /**
     * 判断是否存在这个产品
     *
     * @param id
     * @return
     */
    @Override
    public boolean count(Long id) {
        MassageProduct product = getById(id);
        return product != null;
    }


    @Override
    public boolean insertProduct(MassageProductParam param) {
        // 根据categoryId查询出名称
        MassageProductCategory category = massageProductCategoryService.getById(param.getCategoryId());
        if (category == null) {
            throw new YyghException(500, "该分类不存在");
        }
        MassageProduct massageProduct = new MassageProduct();
        BeanUtils.copyProperties(param, massageProduct);
        massageProduct.setCategoryName(category.getName());
        return save(massageProduct);
    }

    /**
     * 定时任务扫描看产品过期时间
     * 每天晚上12.30点执行
     */
    @Scheduled(cron = "0 30 0 * * ?")
    public void productExpiration() {
        // 1.获取所有的产品
        List<MassageProduct> massageProducts = list();

        // 2.判断他们的上架时间是否在有效时间内
        if (massageProducts == null || massageProducts.isEmpty()) {
            return;
        }


        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String format = simpleDateFormat.format(new Date());


        // 存放需要上架的
        List<Long> up = new ArrayList<>();
        // 存放需要下架的
        List<Long> down = new ArrayList<>();

        // 3.如果没有在就要修改状态 修改了下架
        massageProducts.forEach(item -> {
            String end = item.getEnd();
            String start = item.getStart();
            if (format.compareTo(start) >= 0 && format.compareTo(end) <= 0) {
                // 并且他的状态还是下架的话 就要修改状态了
                if ("1".equals(item.getUp())) {
                    up.add(item.getId());
                }
            } else {
                if ("0".equals(item.getUp())) {
                    down.add(item.getId());
                }
            }

        });

        // 4.如果在的话就要修改为 上架
        if (!up.isEmpty()) {
            // 修改为上架
            for (Long u : up) {
                updateProductStatus(u, 0);
            }
        }


        // 5.修改为下架
        if (!down.isEmpty()) {
            for (Long d : down) {
                updateProductStatus(d, 1);
            }
        }


    }

    /**
     * 修改产品信息
     *
     * @param id
     * @param param
     * @return
     */
    @Override
    public boolean update(Long id, MassageProductParam param) {

        MassageProduct byId = getById(id);
        String name = byId.getName();
        if (!name.equals(param.getName())) {
            LambdaQueryWrapper<MassageProduct> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(MassageProduct::getName, param.getName());
            int count = count(lambdaQueryWrapper);
            if (count > 0) {
                throw new YyghException(500, "该产品名称已存在");
            }
        }

        // 根据categoryId查询出名称
        MassageProductCategory category = massageProductCategoryService.getById(param.getCategoryId());
        if (category == null) {
            throw new YyghException(500, "该分类不存在");
        }
        MassageProduct massageProduct = new MassageProduct();
        BeanUtils.copyProperties(param, massageProduct);
        massageProduct.setId(id);
        massageProduct.setCategoryName(category.getName());
        return updateById(massageProduct);
    }

    /**
     * 删除产品
     *
     * @param id
     * @return
     */
    @Transactional
    @Override
    public boolean delete(Long id) {

        // 首先先删除记录表里面
        visitProductService.deleteByProductId(id);

        if (count(id)) {
            return removeById(id);
        }
        return false;
    }

    /**
     * 获取产品信息
     *
     * @param id
     * @return
     */
    @Override
    public MassageProduct getProduct(Long id) {
        if (count(id)) {
            return getById(id);
        }
        return null;
    }

    /**
     * 获取产品列表（分页查询）
     *
     * @param name
     * @param pageNum
     * @param pageSize
     * @return
     */
    @Override
    public IPage<MassageProductFinalDto> list(String name, String up, String categoryName, Long categoryId, Integer pageNum, Integer pageSize) {
        LambdaQueryWrapper<MassageProduct> wrapper = new LambdaQueryWrapper<>();
        IPage<MassageProduct> page = new Page<>(pageNum, pageSize);
        IPage<MassageProductFinalDto> pageFinal = new Page<>(pageNum, pageSize);

        if (!StringUtils.isEmpty(name)) {
            wrapper.like(MassageProduct::getName, name);
        }
        if (!StringUtils.isEmpty(up)) {
            wrapper.eq(MassageProduct::getUp, up);
        }
        if (categoryId != null) {
            wrapper.eq(MassageProduct::getCategoryId, categoryId);
        }
        if (!StringUtils.isEmpty(categoryName)) {
            wrapper.like(MassageProduct::getCategoryName, categoryName);
        }
        IPage<MassageProduct> productIPage = page(page, wrapper);
        BeanUtils.copyProperties(productIPage, pageFinal);
        List<MassageProduct> records = productIPage.getRecords();

        // 还有就是判断一下是否下架

        // 遍历每个产品，从产品记录表里面获取当前商品预约状态为0的商品总数
        List<MassageProductFinalDto> collect = records.stream().map(massageProduct -> {
            MassageProductFinalDto massageProductFinalDto = new MassageProductFinalDto();
            BeanUtils.copyProperties(massageProduct, massageProductFinalDto);
            LambdaQueryWrapper<VisitProduct> visitProductLambdaQueryWrapper = new LambdaQueryWrapper<>();
            // 根据产品id以及预约状态为0查询出总数
            visitProductLambdaQueryWrapper.eq(VisitProduct::getProductId, massageProduct.getId());
            visitProductLambdaQueryWrapper.eq(VisitProduct::getOk, 0);
            // 将他们全部查询出来遍历每一个，然后将他们的数量相加
            List<VisitProduct> list = visitProductService.list(visitProductLambdaQueryWrapper);
            int needCount = 0;
            if (list != null && !list.isEmpty()) {
                for (VisitProduct visitProduct : list) {
                    needCount += visitProduct.getBuycount();
                }
            }

            massageProductFinalDto.setNeedCount(needCount);
            return massageProductFinalDto;
        }).collect(Collectors.toList());
        pageFinal.setRecords(collect);


//        return productIPage;
        return pageFinal;
    }

    /**
     * 获取产品列表（分页查询）小程序端搜索去除下架
     *
     * @param name
     * @param categoryName
     * @param categoryId
     * @param pageNum
     * @param pageSize
     * @return
     */
    @Override
    public IPage<MassageProduct> listForApp(String name, String categoryName, Long categoryId, Integer pageNum, Integer pageSize) {
        LambdaQueryWrapper<MassageProduct> wrapper = new LambdaQueryWrapper<>();
        IPage<MassageProduct> page = new Page<>(pageNum, pageSize);

        if (name != null) {
            wrapper.like(MassageProduct::getName, name);
        }
        if (categoryId != null) {
            wrapper.eq(MassageProduct::getCategoryId, categoryId);
        }
        if (categoryName != null) {
            wrapper.like(MassageProduct::getCategoryName, categoryName);
        }

        // 今天的日期
        String format = new SimpleDateFormat("yyyy-MM-dd").format(new Date());


        IPage<MassageProduct> productIPage = page(page, wrapper);
        List<MassageProduct> records = productIPage.getRecords();

        if (records != null) {
            List<MassageProduct> collect = records.stream().filter(item -> {
                // 0为上架的
                return "0".equals(item.getUp()) && format.compareTo(item.getStart()) >= 0 && format.compareTo(item.getEnd()) <= 0;
            }).collect(Collectors.toList());

            productIPage.setRecords(collect);
            productIPage.setTotal(collect.size());
            return productIPage;
        }
        return productIPage;
    }

    /**
     * 获取产品列表（分页查询）
     *
     * @param openId
     * @param categoryId
     * @param pageNum
     * @param pageSize
     * @return
     */
    @Override
    public IPage<MassageProductDto> listForAppList(String openId, Long categoryId, Integer pageNum, Integer pageSize) {
        UserBasicInfo user = userBasicInfoService.getUserByOpenId(openId);
        Long userId = user.getId();
        IPage<MassageProductDto> pageDTO = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<MassageProduct> wrapper = new LambdaQueryWrapper<>();
        IPage<MassageProduct> page = new Page<>(pageNum, pageSize);
        if (categoryId != null) {
            wrapper.eq(MassageProduct::getCategoryId, categoryId);
        }
        // 今天的日期
        String format = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        IPage<MassageProduct> productIPage = page(page, wrapper);
        BeanUtils.copyProperties(productIPage, pageDTO);
        List<MassageProduct> records = productIPage.getRecords();
        if (records != null) {
            List<MassageProductDto> result = records.stream().filter(item -> {
                return "0".equals(item.getUp()) && format.compareTo(item.getStart()) >= 0 && format.compareTo(item.getEnd()) <= 0;
            }).map(item -> {
                MassageProductDto massageProductDto = new MassageProductDto();
                BeanUtils.copyProperties(item, massageProductDto);
                // 下面就去看看自己是否已经预约了
                LambdaQueryWrapper<VisitProduct> visitProductLambdaQueryWrapper = new LambdaQueryWrapper<>();
                visitProductLambdaQueryWrapper.eq(VisitProduct::getUserId, userId);
                visitProductLambdaQueryWrapper.eq(VisitProduct::getProductId, item.getId());
                visitProductLambdaQueryWrapper.eq(VisitProduct::getOk, 0); // 这个就表示已经预约了但是还没有去实现的
                VisitProduct one = visitProductService.getOne(visitProductLambdaQueryWrapper);
                if (one == null) {
                    massageProductDto.setStatus(0);
                } else {
                    // 表示有人预约了
                    massageProductDto.setStatus(1);
                    massageProductDto.setBuycount(one.getBuycount());
                    massageProductDto.setVisitProductId(one.getId());
                }

                // 去看这个产品总共预约了多少瓶
                LambdaQueryWrapper<VisitProduct> productLambdaQueryWrapper = new LambdaQueryWrapper<>();
                productLambdaQueryWrapper.eq(VisitProduct::getProductId, item.getId());
                productLambdaQueryWrapper.eq(VisitProduct::getOk, 0); // 这个就表示已经预约了但是还没有去实现的
                List<VisitProduct> list = visitProductService.list(productLambdaQueryWrapper);
                int needCount = 0;
                // 看是否为空
                if (list != null && list.size() > 0) {
                    for (VisitProduct visitProduct : list) {
                        needCount += visitProduct.getBuycount();
                    }
                }
                massageProductDto.setNeedProductCount(needCount);

                return massageProductDto;
            }).collect(Collectors.toList());
            pageDTO.setRecords(result);
            pageDTO.setTotal(result.size());
            return pageDTO;
//            return page;
        }
        return pageDTO;
    }

    /**
     * 产品上下架
     *
     * @param id
     * @param status
     * @return
     */
    @Override
    public Boolean updateProductStatus(Long id, Integer status) {
        String start = "";
        String end = "";
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");

        if (status == 0) {
            // 表示上架
            start = simpleDateFormat.format(new Date(System.currentTimeMillis() - 1000 * 60 * 60 * 24));
            end = simpleDateFormat.format(new Date(System.currentTimeMillis() + 1000L * 60 * 60 * 24 * 90));
        } else {
            // 表示下架

            start = simpleDateFormat.format(new Date(System.currentTimeMillis() - 1000 * 60 * 60 * 24 * 2));
            end = simpleDateFormat.format(new Date(System.currentTimeMillis() - 1000 * 60 * 60 * 24));
        }
        LambdaUpdateWrapper<MassageProduct> massageProductLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        massageProductLambdaUpdateWrapper.eq(MassageProduct::getId, id);
        massageProductLambdaUpdateWrapper.set(MassageProduct::getUp, status);
        massageProductLambdaUpdateWrapper.set(MassageProduct::getStart, start);
        massageProductLambdaUpdateWrapper.set(MassageProduct::getEnd, end);
        boolean update = update(massageProductLambdaUpdateWrapper);
        return update;
    }

}
